package com.rupeng.service;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.LinkedList;
import java.util.List;

import com.rupeng.annotation.RupengCacheable;
import com.rupeng.annotation.RupengClearCache;
import com.rupeng.annotation.RupengUseCache;
import org.springframework.beans.factory.annotation.Autowired;

import com.rupeng.mapper.IManyToManyMapper;
@RupengCacheable
public class ManyToManyBaseService<T, F, S> extends BaseService<T> {
	@Autowired
	private IManyToManyMapper<T, F, S> manyToManyMapper;
	@RupengClearCache
	public void updateFirst(long firstId, Long[] secondIds) {
		try {
			ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
			Type[] classes = type.getActualTypeArguments();
			Class tClass = (Class) classes[0];
			Class fClass = (Class) classes[1];
			Class sClass = (Class) classes[2];
			T t = (T) tClass.newInstance();
			tClass.getDeclaredMethod("set" + fClass.getSimpleName() + "Id", Long.class).invoke(t, firstId);
			// 查找原有数据
			List<T> oldTResult = selectList(t);
			// 把数组中的数据转移到list中（方便下面的操作），并且把无效数据（secondId==null）剔除
			List<Long> secondIdList = new LinkedList<>();
			if (secondIds != null) {
				for (Long secondId : secondIds) {
					if (secondId != null) {
						secondIdList.add(secondId);
					}
				}
			}
			// 比对数据更改，删掉原本在数据库中但现在不在secondIdList中的数据
			if (oldTResult != null) {
				for (T tempT : oldTResult) {
					Long secondId = (Long) tClass.getDeclaredMethod("get" + sClass.getSimpleName() + "Id")
							.invoke(tempT);
					if (!secondIdList.remove(secondId)) {
						this.delete((Long) tClass.getDeclaredMethod("getId").invoke(tempT));
					}
				}
			}
			// 把secondIdList中剩余的添加到数据库
			for (Long secondId : secondIdList) {
				tClass.getDeclaredMethod("set" + sClass.getSimpleName() + "Id", Long.class).invoke(t, secondId);
				this.insert(t);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	@RupengClearCache
	public void updateSecond(long secondId, Long[] firstIds) {
		try {
			ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
			// 泛型类的Class对象
			Type[] genericTypes = type.getActualTypeArguments();
			Class tClass = (Class) genericTypes[0];// T
			Class fClass = (Class) genericTypes[1];// F
			Class sClass = (Class) genericTypes[2];// S
			// 通过反射创建泛型T的对象
			T t = (T) tClass.newInstance();
			// 获取并调用T的set(Second)Id方法
			tClass.getDeclaredMethod("set" + sClass.getSimpleName() + "Id", Long.class).invoke(t, secondId);
			// 查询旧的关联关系
			List<T> oldTResult = selectList(t);
			// 把数组中的数据转移到list中（方便下面的操作），并且把无效数据（firstId==null）剔除
			List<Long> firstIdList = new LinkedList<>();
			if (firstIds != null) {
				for (Long firstId : firstIds) {
					if (firstId != null) {
						firstIdList.add(firstId);
					}
				}
			}
			// 2 删掉原本在数据库中但现在不在firstIdList中的数据
			if (oldTResult != null) {
				for (T tempT : oldTResult) {
					// 拿到tempT对象的firstId
					Long firstId = (Long) tClass.getDeclaredMethod("get" + fClass.getSimpleName() + "Id")
							.invoke(tempT);
					if (!firstIdList.remove(firstId)) {
						delete((Long) tClass.getDeclaredMethod("getId").invoke(tempT));
					}
				}
			}
			// 3 把firstIdList中剩余的添加到数据库
			for (Long firstId : firstIdList) {
				tClass.getDeclaredMethod("set" + fClass.getSimpleName() + "Id", Long.class).invoke(t, secondId);
				insert(t);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	@RupengClearCache
	public int deleteByFirstId(long firstId) {
		return manyToManyMapper.deleteByFirstId(firstId);
	}
	@RupengClearCache
	public int deleteBySecondId(long secondId) {
		return manyToManyMapper.deleteBySecondId(secondId);
	}
	@RupengUseCache
	public List<F> selectFirstListBySecondId(long secondId) {
		return manyToManyMapper.selectFirstListBySecondId(secondId);
	}
	@RupengUseCache
	public F selectFirstOneBySecondId(long secondId) {
		List<F> result = manyToManyMapper.selectFirstListBySecondId(secondId);
		if (result == null || result.size() == 0) {
			return null;
		}
		return result.get(0);
	}
	@RupengUseCache
	public List<S> selectSecondListByFirstId(long firstId) {
		return manyToManyMapper.selectSecondListByFirstId(firstId);

	}
	@RupengUseCache
	public S selectSecondOneByFirstId(long firstId) {
		List<S> result = manyToManyMapper.selectSecondListByFirstId(firstId);
		if (result == null || result.size() == 0) {
			return null;
		}
		return result.get(0);
	}
}
